/*
 * $Id: ProdiagsCommandRefBuilder.java,v 1.2 2009/08/20 21:37:36 navdeep_mahajan Exp $
 * 
 * Copyright (C) 2008 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.onwatch.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;

import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.ASCUtil;
import com.ge.healthcare.autosc.common.database.dao.ISweepPropertiesDAO;
import com.ge.healthcare.autosc.common.exceptions.BasicException;
import com.ge.healthcare.autosc.common.prodiags.ProdiagsScheduleTask;
import com.ge.healthcare.autosc.common.prodiags.ProdiagsTaskParamsMap;
import com.ge.healthcare.autosc.common.util.ApplicationInfo;
import com.ge.healthcare.autosc.common.util.PropertyConstants;
import com.ge.healthcare.autosc.onwatch.exception.CommandRefBuilderException;
import com.ge.healthcare.autosc.onwatch.pojo.OnwatchTaskInfo;

public class ProdiagsCommandRefBuilder extends BaseCommandRefBuilder {

	private ProdiagsTaskParamsMap taskParamsMap = null;
	private String firstTaskId = null;
	private static String PD_ADD_TASK = ApplicationInfo.getInstance().getProperty(PropertyConstants.PD_ADD_TASK);
	private static String PD_MODIFY_TASK = ApplicationInfo.getInstance().getProperty(PropertyConstants.PD_MODIFY_TASK);
	private static String PD_DELETE_TASK = ApplicationInfo.getInstance().getProperty(PropertyConstants.PD_DELETE_TASK);
	private static String PD_INSTALL_TASK = ApplicationInfo.getInstance().getProperty(PropertyConstants.PD_INSTALL_TASK);
	private static String PD_UNINSTALL_TASK = ApplicationInfo.getInstance().getProperty(PropertyConstants.PD_UNINSTALL_TASK);
	
	public ProdiagsCommandRefBuilder() {
		super();
	}
	
	public String build(String content, OnwatchTaskInfo onwatchTaskInfo) 
		throws CommandRefBuilderException {
		createProdiagsTaskParamsMap(onwatchTaskInfo);
		String commands = buildReference(content, onwatchTaskInfo);
		return commands;
	}
	
	private void createProdiagsTaskParamsMap(OnwatchTaskInfo onwatchTaskInfo) 
		throws CommandRefBuilderException {
		try {
			taskParamsMap = new ProdiagsTaskParamsMap(onwatchTaskInfo.getRequestProperties());
		} catch (BasicException be) {
			throw new CommandRefBuilderException("Unable to load prodiags task parameters", OnWatchCodeConstants.PRC_F_OWR_034);
		}
	}
	
	private String buildReference(String content, OnwatchTaskInfo onwatchTaskInfo) 
		throws CommandRefBuilderException {
		String methodName = "buildReference";
		StringBuffer newContent = new StringBuffer();
		try {
			BufferedReader reader = new BufferedReader(new StringReader(content));
			String line = null;
			// Read content one line at a line as content cannot be too long for RE
			RE nameSub = new RE("^(.*)%REF:PD_CMD:(.*):REF%(.*)$");
			while((line = reader.readLine()) != null) {
				if(nameSub.match(content)) {
					String firstTaskId = nameSub.getParen(2);
					String prodiCmds = constructProdiagsTaskCmd(onwatchTaskInfo, firstTaskId);
					ASCLogger.info(this.getClass(), methodName,
							"Substitute: %REF:PD_CMD% with value: "
									+ prodiCmds, true);
					newContent.append(nameSub.getParen(1)).append(prodiCmds).append(nameSub.getParen(3));
				} else {
					newContent.append(line);
				}
				newContent.append("\n");
			}
		} catch (IOException ioe) {
			
		} catch (RESyntaxException reException) {
			throw new CommandRefBuilderException(
					"Failed performing RE Conversion", reException, OnWatchCodeConstants.PRC_F_OWR_031);
		}
		return newContent.toString();
	}
	
	private String constructProdiagsTaskCmd(OnwatchTaskInfo onwatchTaskInfo, String firstTaskId) 
		throws CommandRefBuilderException {
		StringBuffer content = new StringBuffer();
		this.firstTaskId = firstTaskId;
		Integer[] taskOrders = taskParamsMap.getProdiagsTaskIndexes();
		for(int idx=0;idx<taskOrders.length;idx++) {
			ProdiagsScheduleTask task = taskParamsMap.getProdiagsTask(taskOrders[idx]);
			if(idx == 0) {
				task.markFirstTask();
			}
			if((idx + 1) < taskOrders.length) {
				task.setNextTask(taskParamsMap.getProdiagsTask(taskOrders[idx+1]));
			}
			String commandFileId = null;
			if(task.getTaskType().equalsIgnoreCase(PD_ADD_TASK)) {
				commandFileId = ISweepPropertiesDAO.PRODI_ADDTASK_CMD_FILE;
			} else if (task.getTaskType().equalsIgnoreCase(PD_MODIFY_TASK)) {
				commandFileId = ISweepPropertiesDAO.PRODI_MODIFYTASK_CMD_FILE;
			} else if (task.getTaskType().equalsIgnoreCase(PD_DELETE_TASK)) {
				commandFileId = ISweepPropertiesDAO.PRODI_DELETETASK_CMD_FILE;
			} else if (task.getTaskType().equalsIgnoreCase(PD_INSTALL_TASK)) {
				commandFileId = ISweepPropertiesDAO.PRODI_INSTALLTASK_CMD_FILE;
			} else if (task.getTaskType().equalsIgnoreCase(PD_UNINSTALL_TASK)) {
				commandFileId = ISweepPropertiesDAO.PRODI_UNINSTALLTASK_CMD_FILE;
			} else {
				throw new CommandRefBuilderException("Unknown prodiags task type " + task.getTaskType(), OnWatchCodeConstants.PRC_F_OWR_032);
			}

			content.append(addCommand(onwatchTaskInfo, task, commandFileId));
		}
		return content.toString();
	}
	
	private String addCommand(OnwatchTaskInfo onwatchTaskInfo, 
							  ProdiagsScheduleTask task,
							  String commandFileId) 
		throws CommandRefBuilderException {
		StringBuffer content = new StringBuffer();
		FileInputStream fis = null;
		File commandFile = onwatchTaskInfo.getRefCmdFile(commandFileId);
		if(commandFile != null) {
			try {
				fis = new FileInputStream(commandFile);
				BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
				String line = null;
				while((line = reader.readLine()) != null) {
					line = substitution(line, onwatchTaskInfo, task);
					content.append(line);
					content.append("\n");
				}
			} catch (FileNotFoundException fnfe) {
				throw new CommandRefBuilderException("command File " + commandFile.getPath() + " does not exist",
						fnfe, OnWatchCodeConstants.PRC_F_OWR_018);
			} catch (IOException ioe) {
				throw new CommandRefBuilderException("Failed reading command file " + commandFile.getPath() +
								"because of IOException.", ioe, OnWatchCodeConstants.PRC_F_OWR_030);
			} finally {
				ASCUtil.silentlyClose(fis);
			}
		} else {
			throw new CommandRefBuilderException("Cannot find reference command file with name " + 
					commandFileId, OnWatchCodeConstants.PRC_F_OWR_033);
		}
		return content.toString();
	}
	
	
	private String substitution(String line, 
								OnwatchTaskInfo onwatchTaskInfo, 
								ProdiagsScheduleTask task) 
		throws CommandRefBuilderException {
		line = substituteByParam(line, onwatchTaskInfo, task);
		line = substituteById(line, task);
		return line;
	}	
	
	private String substituteByParam(String line,
									 OnwatchTaskInfo onwatchTaskInfo, 
									 ProdiagsScheduleTask task) 
		throws CommandRefBuilderException {
		String methodName = "substitution";
		if(onwatchTaskInfo.hasDynamicArg()) {
			if(!ASCUtil.isNullOrEmptySet(task.getParamNames())) {
				RE checkForVar;
				try {
					checkForVar = new RE("%PARAM:[A-Za-z0-9_-]+%");
					if(checkForVar.match(line)) {
						for(String name: task.getParamNames()) {
							RE nameSub = new RE("^(.*)%PARAM:" + name + "%(.*)$");
							while (nameSub.match(line)) {
								ASCLogger.info(this.getClass(), methodName,
										"Substitute: %PARAM:" + name + "% with value: "
												+ task.getParamValue(name), true);
								line = nameSub.getParen(1) + task.getParamValue(name) + nameSub.getParen(2);
							}
						}
					}
				} catch (RESyntaxException reException) {
					throw new CommandRefBuilderException(
							"Failed performing RE Conversion", reException, OnWatchCodeConstants.PRC_F_OWR_031);
				}
			}
		}
		return line;
	}
	
	private String substituteById(String line, 
			ProdiagsScheduleTask currTask) throws CommandRefBuilderException {
		String methodName = "substituteById";
		try {
			RE nameSub = new RE("^(.*)%CURR_ID%(.*)$");
			while (nameSub.match(line)) {
				String currId = null;
				if(currTask.isFristTask() && !ASCUtil.isNullOrEmpty(firstTaskId)) {
					currId = firstTaskId;
				} else {
					currId = currTask.getTaskTypeId();
				}
				ASCLogger.info(this.getClass(), methodName,
						"Substitute: %CURR_ID% with value: " + currId, true);
				line = nameSub.getParen(1) + currId + nameSub.getParen(2);
			}

			ProdiagsScheduleTask nextTask = currTask.getNextTask();
			nameSub = new RE("^(.*)%NEXT_ID%(.*)$");
			while (nameSub.match(line)) {
				String nextId = null;
				if(nextTask != null) {
					nextId = nextTask.getTaskTypeId();
				}
				String msg = null;
				if(ASCUtil.isNullOrEmpty(nextId)) {
					msg = "Substitute: %NEXT_ID% with empty value";
					line = nameSub.getParen(1) + "none" + nameSub.getParen(2);
				} else {
					msg = "Substitute: %NEXT_ID% with value " + nextId;
					line = nameSub.getParen(1) + nextId + nameSub.getParen(2);
				}
				ASCLogger.info(this.getClass(), methodName, msg, true);
			}
		} catch (NoSuchAlgorithmException nsae) {
			throw new CommandRefBuilderException("Failed generating Id for task " + currTask);
		} catch (UnknownHostException uhe) {
			throw new CommandRefBuilderException("Failed generating Id for task " + currTask);
		} catch (RESyntaxException reException) {
			throw new CommandRefBuilderException(
					"Failed performing RE Conversion", reException, OnWatchCodeConstants.PRC_F_OWR_031);
		}	
		return line;
	}
}
